package sim_moteur.element.animeaux;

import sim_moteur.Coordonnee;
import sim_moteur.Terrain;
import sim_moteur.element.Vivant;
import sim_moteur.element.vegetal.Vegetal;
import util.Sequence;
import util.SequencePredeterminee;

public class Animal extends Vivant {

	public final static float SEUIL_DE_REPOS = 5f;
	public final static float SEUIL_DE_FAMINE = 4f;
	public final static float SEUIL_DE_FAIM = 8f;
	public final static float SEUIL_DE_FATIGUE = 8f;
	public final static float DISCRIMINATEUR_FATIGUE_VIE = 15f;
	public final static float SEUIL_EPUISEMENT = 14f;

	public final static float COUT_PAR_PAS_DE_TEMPS = 0.05f;
	public final static float COUT_DEPLACEMENT = 0.25f;
	public final static float COUT_REPOS = 0.1f;
	public final static float FATIGUE_PAR_DEPLACEMENT = 0.3f;
	public final static float REPOS_PAR_PAS_DE_TEMPS = 1f;
	public final static float ENERGIE_PAR_VEGETAL = 0.3f;
	public final static float FATIGUE_POUR_MANGER = 0.2f;
	public final static float FATIGUE_POUR_MARCHER = 1f;
	public final static float FATIGUE_POUR_REPOS = -2f;

	public final static float ENERGIE_PAR_PAS_DE_TEMPS = 1;

	public final static int RANDOM_DISCRIMINATEUR_POUR_MARCHER = 0;
	public final static int RANDOM_DISCRIMINATEUR_POUR_REPOSER = 1;
	public final static int RANDOM_DISCRIMINATEUR_POUR_MANGER = 2;

	private float fatigue;

	public Animal(String name, float vitalite) {
		super(name, vitalite);
		fatigue = 0;// l'animal part en pleine forme
	}

	@Override
	public boolean vit(long step) {
		// On met à jour l'état de l'animal
		determineEtat();

		Terrain terrain = Terrain.getInstance();
		Vegetal vegetal = terrain.trouveUnVegetal(this.coordonnees);

		// On réagit selon l'etat
		switch (etat) {
		case ANIMAL_FRINGALE:
		case ANIMAL_AFFAME:
			if (vegetal != null)
				mange(vegetal);
			else
				marche();
			break;
		case ANIMAL_FATIGUE:
		case ANIMAL_EPUISE:
			repose();
			break;
		case VIVANT:
			// agit au hazard
			int decision = (int) (Math.random() * 3);
			switch (decision) {
			case RANDOM_DISCRIMINATEUR_POUR_MANGER:
				if (vegetal != null)
					mange(vegetal);
				else
					repose();
				break;
			case RANDOM_DISCRIMINATEUR_POUR_MARCHER:
				marche();
				break;
			case RANDOM_DISCRIMINATEUR_POUR_REPOSER:
				repose();
				break;
			}

		}
		return etat != Etat.MORT;
	}

	private void determineEtat() {
		// Les états sont classés par ordre de priorité
		// Les écrasements d'états sont voulus!

		etat = Etat.VIVANT;
		if (fatigue > SEUIL_DE_FATIGUE)
			etat = Etat.ANIMAL_FATIGUE;
		if (vie < SEUIL_DE_FAIM)
			etat = Etat.ANIMAL_FRINGALE;
		if (vie < SEUIL_DE_FAMINE)
			etat = Etat.ANIMAL_AFFAME;
		if (fatigue > SEUIL_EPUISEMENT)
			etat = Etat.ANIMAL_EPUISE;
		if (vie < 0)
			etat = Etat.MORT;
	}

	/**
	 * L'animal marche aléatoirement autour de lui.
	 * 
	 */
	public void marche() {
		int direction;
		Terrain terrain = Terrain.getInstance();
		Coordonnee nouvelleCoordonnee;
		// Sequence sequence = new RandomSansRepetition(
		// Coordonnee.NOMBRE_DE_DIRECTION);
		Sequence sequence = new SequencePredeterminee();

		do {
			direction = sequence.nextNumber();
			nouvelleCoordonnee = coordonnees.retourneACote(direction);
			// Si l'animal ne peut pas marcher il reste en place

		} while (!terrain.deplace(this, nouvelleCoordonnee));

		// coordonnees = nouvelleCoordonnee;
		fatigue += FATIGUE_POUR_MARCHER;
		vie -= COUT_DEPLACEMENT;
		action = Action.ANIMAL_MARCHE;
	}

	public void mange(Vegetal vegetal) {
		vegetal.transfertVie(this, ENERGIE_PAR_PAS_DE_TEMPS);
		fatigue += FATIGUE_POUR_MANGER;
		action = Action.ANIMAL_MANGE;
		// L'animal est resté en place.
		coordonneesPrecedentes = new Coordonnee(coordonnees);
	}

	public void repose() {
		fatigue += FATIGUE_POUR_REPOS;
		fatigue = Math.max(0f, fatigue);
		vie -= COUT_REPOS;
		action = Action.ANIMAL_REPOSE;
		// L'animal est resté en place.
		coordonneesPrecedentes = new Coordonnee(coordonnees);
	}

	public void meurt() {
		action = Action.MOURIR;
		etat = Etat.MORT;
		vie= -1.0f;
	}

	public String toString() {
		return super.toString() + "fatigue:" + fatigue + "\n";
	}

}
